﻿#ifndef DPSOCKLINK_H
#define DPSOCKLINK_H

#include "oscbb.h"

#ifdef __cplusplus
extern "C" {
#endif

class DPSockLink
{
public:
    DPSockLink();

    int create(DMapParam &param);
    int get_protocol();

    static void svr_recv_data(void *ctx,/* struct epoll_event *ev, */uint64_t cur_time);
    static void tcp_connection(void *ctx,/* struct epoll_event *ev, */uint64_t cur_time);
    static void tcp_svr_recv_data(void *ctx,/* struct epoll_event *ev,*/ uint64_t cur_time);
    static void inter_recv_data(void *ctx,/* struct epoll_event *ev, */uint64_t cur_time);

    ///发送函数
    int buf_send_data(void *context, void *buf, int len, uint32_t rmt_ip, uint16_t rmt_port);
    //tcp send
    int tcp_svr_send_data(int fd, void *buf, int len);
    //udp send
    int svr_send_data(void *buf, int len, uint32_t rmt_ip, uint16_t rmt_port);

private:
    /// 创建所有套接字
    int create_socket();
#ifdef IO_EPOLL
     /// 创建事件模型
    int create_ev_model();
#endif

    int udp_recv_data(int fd, FInetDataCb cb, void *cb_ctx, uint64_t cur_time);

    /// unix_datagram recv data & cb
    int udp_unix_recv_data(int fd, FUnixDataCb cb, void *cb_ctx, uint64_t cur_time);

    void accept_new_client(/*struct epoll_event *ev,*/ uint64_t cur_time);

    int tcp_recv_data(int fd, FTcpDataCb cb, void *cb_ctx,  struct sockaddr_in &addr, uint64_t cur_time);

    /// 套接字任务
    static void *sock_routine(void *arg);
#ifdef IO_EPOLL
     /// 处理epoll事件
    void sock_deal_events(int num, uint64_t time);

    /// 处理触发器
    void sock_deal_trigger(uint64_t time);
#endif
    int tcp_find_socket(uint32_t ip, uint16_t port);

    void deal_select(uint64_t time);

private:

    DMapParam  dp_param;

    SOCKHANDLE		 udp_fd;
    SOCKHANDLE       tcp_fd;
    SOCKHANDLE		 unix_fd;

#ifdef IO_EPOLL
    TSockEpollCtx       sock_svr_ctx;
    TSockEpollCtx       sock_inter_ctx;
    TSockEpollCtx       tcp_sock_svr_ctx;
#elif IO_SELECT
    SOCKHANDLE          nfds;
    TSockSelectCtx      sock_svr_ctx;
    TSockSelectCtx      sock_inter_ctx;
    TSockSelectCtx      tcp_sock_svr_ctx;
#endif

    static const int MAX_CLIENT_NUM  = 10;
    struct CDPClientCtx
    {
        CDPClientCtx()
        {
            birth_time  = 0;
            client_link = NULL;
        }
#ifdef IO_EPOLL
        TSockEpollCtx       client_sock_ctx;
#elif IO_SELECT
        TSockSelectCtx      client_sock_ctx;
#endif
        struct sockaddr_in  rmt_addr;
        uint64_t            birth_time;
        DPSockLink         *client_link;
    }client_ctx[MAX_CLIENT_NUM];

    int                 data_len;
    char                buf[DMAP_MAX_DATA_LEN];


    struct sockaddr_in  rmt_addr;

    struct sockaddr_un  rmt_addr_unix;
    socklen_t           rmt_addr_len;

    /// for tcp
   char                *recvbuf;
   int                 bufsize;
   int                 buflen;

   char                *sendbuf;
   int                 sendbuf_size;
   int                 sendbuf_len;

   uint32_t            trigger_count;
#ifdef IO_EPOLL
/// epoll param
    int                 ep_fd;              /// epoll fd
    uint32_t            ep_max_events;
    int                 ep_timeout;
    struct epoll_event  *ep_ev;
#endif

    pthread_t           link_task_pid;
    bool                link_task_exit;
    int                 protocol;

    unsigned int    timeout;        /// 单位:ms

};

#ifdef __cplusplus
}
#endif

#endif // DPSOCKLINK_H
